<?php
/**
 * "Tag" Model
 *
 * @author hiscaler <hiscaler@gmail.com>
 * @link http://www.yuandot.com/
 * @copyright Copyright &copy; 2009-2010 Yuandot Information Technology CO.,LTD.
 * @license http://doit.yuandot.com/license/
 */

class Tag extends CActiveRecord {

    /**
     * The followings are the available columns in table 'www_tags':
     * @var integer $id
     * @var string $name
     * @var string $type
     * @var integer $frequency
     * @var integer $created
     */

    /**
     * Returns the static model of the specified AR class.
     * @return CActiveRecord the static model class
     */
    public static function model($className=__CLASS__) {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName() {
        return '{{tags}}';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules() {
    // NOTE: you should only define rules for those attributes that
    // will receive user inputs.
        return array(
            array('name, type', 'required'),
            array('frequency, created', 'numerical', 'integerOnly' => true),
            array('name, type', 'length', 'max' => 128),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations() {
    // NOTE: you may need to adjust the relation name and the related
    // class name for the relations automatically generated below.
        return array(
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels() {
        return array(
            'id' => 'Id',
            'name' => Yii::t('tags', 'name'),
            'type' => Yii::t('tags', 'type'),
            'frequency' => Yii::t('tags', 'frequency'),
            'created' => Yii::t('common', 'created'),
        );
    }

    const TYPE_POST = 'post';
    const TYPE_PRODUCT = 'product';
    const TYPE_CASE = 'case';
    const TYPE_VIDEO = 'video';
    const TYPE_ALBUM = 'album';
    public function getTypeOptions() {
        return array(
            self::TYPE_POST => Yii::t('tag', 'type_post'),
            self::TYPE_PRODUCT=> Yii::t('tag', 'type_product'),
            self::TYPE_CASE => Yii::t('tag', 'type_case'),
            self::TYPE_VIDEO => Yii::t('tag', 'type_video'),
            self::TYPE_ALBUM => Yii::t('tag', 'type_album'),
        );
    }

    /*
     *获取标签类型名称 
     */
    public function getTypeName() {
        $options = $this->typeOptions;
        return (isset($this->type)) ? Yii::t('tag', "type_{$this->type}") : "unknown";
    }

    /**
     * Returns tag names and their corresponding weights.
     * Only the tags with the top weights will be returned.
     * @param integer the maximum number of tags that should be returned
     * @return array weights indexed by tag names.
     */
    public function findTagWeights($type = null, $limit = 20) {
        $criteria = new CDBCriteria();
        if (($type !== null) && array_key_exists($type, $this->typeOptions)) {
            $criteria->condition = "type = \"{$type}\"";
        } else {
            return array();
        }
        $criteria->order = 'frequency DESC';
        $criteria->limit = $limit;
        $models = $this->findAll($criteria);

        $total = 0;
        foreach($models as $model)
            $total += $model->frequency;

        $tags = array();
        if($total > 0) {
            foreach($models as $model)
                $tags[$model->name] = 8 + (int)(16 * $model->frequency / ($total + 10));
            ksort($tags);
        }
        return $tags;
    }

    /**
     * Suggests a list of existing tags matching the specified keyword.
     * @param string the keyword to be matched
     * @param integer maximum number of tags to be returned
     * @return array list of matching tag names
     */
    public function suggestTags($keyword, $limit = 20) {
        $tags = $this->findAll(array(
            'condition' => 'name LIKE :keyword',
                'order' => 'frequency DESC, Name',
                'limit' => $limit,
                'params' => array(
                ':keyword' => "%$keyword%",
            ),
        ));
        $names = array();
        foreach($tags as $tag)
            $names[] = $tag->name;
        return $names;
    }

    public static function string2array($tags) {
        return preg_split('/\s*,\s*/', trim($tags), -1, PREG_SPLIT_NO_EMPTY);
    }

    public static function array2string($tags) {
        return implode(',', $tags);
    }

    // Update Frequency
    public function updateFrequency($oldTags, $newTags, $type = null) {
        if (($type !== null) && array_key_exists($type, $this->typeOptions)) {
            $oldTags = self::string2array($oldTags);
            $newTags = self::string2array($newTags);
            $this->addTags(array_values(array_diff($newTags, $oldTags)), $type);
            $this->removeTags(array_values(array_diff($oldTags, $newTags)), $type);
        }
    }

    // Add Tags
    public function addTags($tags, $type = null) {
        if (($type !== null) && array_key_exists($type, $this->typeOptions)) {
            $criteria = new CDbCriteria;
            $criteria->condition = 'type = "' . $type . '"';
            $criteria->addInCondition('name', $tags);
            $this->updateCounters(array('frequency' => 1), $criteria);
            foreach($tags as $name) {
                if(!$this->exists('name = :name AND type = :type', array(':name' => $name, ':type' => $type))) {
//                if(!$this->exists('name=:name', array(':name' => $name))) {
                    $tag = new Tag;
                    $tag->type = $type;
                    $tag->name = $name;
                    $tag->frequency = 1;
                    $tag->save();
                }
            }
        }        
    }

    // Remove Tags
    public function removeTags($tags, $type = null) {
        if (($type !== null) && array_key_exists($type, $this->typeOptions)) {
            if (empty($tags)) return;
            $criteria = new CDbCriteria;
            $criteria->condition = 'type = "' . $type . '"';
            $criteria->addInCondition('name', $tags);
            $this->updateCounters(array('frequency' => -1), $criteria);
            $this->deleteAll('type = "' . $type. '" AND frequency <= 0');
        }
    }

    public function behaviors() {
        return array(
            'CTimestampBehavior' => array(
                'class' => 'zii.behaviors.CTimestampBehavior',
                'createAttribute' => 'created',
            )
        );
    }
}
